#filename = r'D:\Document\Madlee\Job\CPMD\Fox-7\2500K\clean_rxn.txt'
#filename = r'D:\Document\Madlee\Job\CPMD\Fox-7\3000K\clean_rxn.txt'
#filename = r'D:\Document\Madlee\Job\CPMD\Fox-7\3500K\clean_rxn.txt'
filename = r'D:\Document\Madlee\Job\CPMD\Fox-7\4000K\clean_rxn.txt'

cutoff = 0.0

mols = [
# Activity
3,
103,
60,
90,
128,
67,
371,
2,
343,
161,
1,
6,
47,
73,
127,
34,
9,


# avg_life
559,
90,
781,
1715,
1006,
294,
103,
128,
371,
343,

]

mols = [i for i in set(mols)]
mols.sort()

class AdjList:
    def __init__(self, edges):
        self.nodes = {}
        for i, j in edges:
            if i not in self.nodes:
                self.nodes[i] = ([], [j])
            else:
                self.nodes[i][1].append(j)
            if j not in self.nodes:
                self.nodes[j] = ([i], [])
            else:
                self.nodes[j][0].append(i)
    
    def in_degree(self, v):
        return len(self.nodes[v][0])
        
    def out_degree(self, v):
        return len(self.nodes[v][1])
        
    def remove_node(self, v):
        for i in self.nodes[v][0]:
            self.nodes[i][1].remove(v)
        for j in self.nodes[v][1]:
            self.nodes[j][0].remove(v)
        del self.nodes[v]
            
    def remove_edge(self, v1, v2):
        self.nodes[v1][1].remove(v2)
        self.nodes[v2][0].remove(v1)
        
def handle_line(line):
    result = []
    for j in line.split('+'):
        j = j.strip()[:-1]
        if j[0] == '[':
            factor = 1
            j = j[1:]
        else:
            factor = int(j[0:j.find('[')])
            j = j[j.find('[')+1:]
        key = int(j)
        result.append((key, factor))
    return result

def create_graph(file):
    file.next()
    edges = {}
    for i in file:
        tokens = i.split('|')
        n = int(tokens[3].strip())
        r, p = tokens[2].split('=')
        r = handle_line(r)
        p = handle_line(p)
        for molR, fR in r:
            for molP, fP in p:
                # edges[(molR, molP)] = fR*fP*n
                edges[(molR, molP)] = n
    keys = [i for i in edges.iterkeys()]
    return AdjList(keys), edges

def bft(g, v, visitor, color=None):
    i = 0
    queue = [v]
    if color is None:
        color = {}
    color[v] = 1
    
    while i < len(queue):
        v = queue[i]
        i += 1
        visitor.start(g, v)
        for j in g.nodes[v][1]:
            if j in color:
                visitor.back(g, j, v)
            else:
                queue.append(j)
                color[j] = 1
                visitor.find(g, j, v)
        visitor.finish(g, v)
        color[v] = 2
        
class DefaultVisitor:
    def start(self, g, v):
        pass
        
    def finish(self, g, v):
        pass

    def find(self, g, target, source):
        pass
        
    def back(self, g, target, source):
        pass
        
class ScoreVisitor(DefaultVisitor):
    def __init__(self, nodes, edges):
        self.nodes = nodes
        self.edges = edges
        self.score = {}
    
    def find(self, g, target, source):
        e = self.edges[(source, target)]
        n = self.nodes[source]
        self.score[target] = self.score[source] * e / n
        
    def back(self, g, target, source):
        e = self.edges[(source, target)]
        n = self.nodes[source]
        self.score[target] += self.score[source] * e / n
    
def count_score(g, e, v0):
    nodes = {}
    for i in g.nodes.iterkeys():
        nodes[i] = g.out_degree(i)
    visitor = ScoreVisitor(nodes, e)
    visitor.score[v0] = 1.0
    bft(g, v0, visitor)
    visitor.score[v0] -= 1.0
    return visitor.score
    
    
class ShortCutVisitor(DefaultVisitor):
    def __init__(self):
        self.score = {}
    
    def find(self, g, target, source):
        self.score[target] = self.score[source] + 1
        
        
def shortcut(g, e, v0):
    nodes = {}
    visitor = ShortCutVisitor()
    visitor.score[v0] = 0
    bft(g, v0, visitor)
    return visitor.score



if __name__ == '__main__':
    print len(mols), mols
    # mols = [1, 2, 5, 23, 47, 67, 73, 90, 103, 127, 128, 161, 166, 294, 343, 371, 559, 647, 781, 855, 1006, 1557, 1568, 1631, 1632, 1648, 1715, 1746]
    # mols = [1, 2, 4, 5, 9, 23, 47, 60, 61, 73, 90, 103, 127, 128, 166, 215] # 2500K
    # mols = [1, 2, 60, 73, 90, 103, 128, 166, 294, 343, 371, 454, 480, 497, 509, 520, 526, 559] # 3000 K
    # mols = [1, 2, 27, 47, 60, 67, 90, 103, 166, 161, 215, 294, 343, 559, 687, 738, 778, 781, 1006] # 3500 K
    mols = [1, 2, 9, 47, 67, 73, 127, 128, 343, 371, 559, 1006, 1715] # 4000K
    with open(filename) as file:
        g, e = create_graph(file)
    count = 0

    for i in mols:
        score = shortcut(g, e, i)
        list = []
        for k, v in score.iteritems():
            if k != i and k in mols:
                list.append((v, k))
            
        list.sort()
        for v, k in list:
            if True: # v == 1:
                print i, "-->", k, v

    for i in mols:
        score = count_score(g, e, i)
        list = []
        for k, v in score.iteritems():
            if k != i and k in mols and v > cutoff:
                list.append((-v, k))
            
        list.sort()
        for v, k in list:
            if v < -0.1:
                print i, "-->", k, "(", -v, ")"
            
